package m.store.service;

import m.base.model.StoreInfo;
import m.base.model.UserInfo;
import m.base.util.PowerUtil;
import m.common.model.util.*;
import m.common.service.Service;
import m.store.model.*;
import m.store.task.GoodsOutRecordSupport;
import m.store.task.GuestStockSupport;
import m.store.task.MonthRecordSupport;
import m.store.task.StoreGoodsSupport;
import m.system.exception.MException;
import m.system.util.GenerateID;
import m.system.util.NumberUtil;
import m.system.util.ObjectUtil;
import m.system.util.StringUtil;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class StockInfoService extends Service {
    public String save(StockInfo model, List<GoodsStockRecord> goodsList) throws Exception {
        if(null==goodsList||goodsList.isEmpty()) throw new MException(this.getClass(),"请添加入库商品明细");
        ModelQueryCheck.init(model)
            .checkNotNull("stockDate","入库日期不能为空")
            .checkNotNull("guest.oid","请选择供货客户")
            .checkNotNull("status","状态错误")
            .checkStrEq("status",OrderModel.Status_Register,"登记状态才能修改")
            .doCheck(false,true);
        if(!StockInfo.Type_Begin.equals(model.getType()))
            PowerUtil.verifyAccountDate(model.getStockDate(),"入库日期");
        String msg="";
        if(ObjectUtil.isEmptyOid(model)){
            model.setOid(GenerateID.generatePrimaryKey());
            ModelUpdateUtil.insertModel(model);
            msg="保存成功";
        }else{
            ModelUpdateUtil.updateModel(model,"guest.oid","stockDate","remark");
            msg="修改成功";
        }
        ModelUpdateUtil.delete(GoodsStockRecord.class, QueryCondition.eq("stock.oid",model.getOid()));
        Set<String> numMap=new HashSet<>();
        for(GoodsStockRecord record : goodsList){
            ModelQueryCheck.init(record)
                .checkNotNull("goods.oid","请选择商品信息")
                .checkNotNull("price","请输入单价")
                .checkNumberRange("price",0D,999999999D,"单价不能小于0")
                .checkNotNull("stockNum","请输入数量")
                .checkNumberRange("stockNum",1D,999999999D,"数量不能小于1")
                .checkNotNull("preferential","请输入优惠金额")
                .doCheck(false,true);
            String goodsOid=record.getGoods().getOid();
            StoreGoods goods=ModelQueryList.getModel(record.getGoods());
            if(numMap.contains(goodsOid)) throw new MException(this.getClass(),goods.getName()+" 重复添加了");
            numMap.add(record.getGoods().getOid());
            record.setOid(GenerateID.generatePrimaryKey());
            record.setStock(model);
            record.setStore(model.getStore());
            record.setOperDate(new Date());
            record.setStockAmount(NumberUtil.round(record.getStockNum()*record.getPrice()-record.getPreferential(),2));
            record.setPreferentialPrice(NumberUtil.round((record.getStockNum()*record.getPrice()-record.getPreferential())/record.getStockNum(),2));
            record.setSurplusNum(record.getStockNum());
            record.setSurplusAmount(record.getStockAmount());
        }
        ModelUpdateUtil.insertModels(goodsList.toArray(new GoodsStockRecord[0]));
        updateAmount(model.getOid(),model.getStore().getOid(),model.getGuest().getOid());
        return msg;
    }
    protected void updateAmount(String oid,String storeOid,String guestOid) throws MException {
        boolean noAccount=storeOid.equals(guestOid);
        ModelUpdate.init(StockInfo.class)
            .set("stockAmount",GoodsStockRecord.class,"ifnull(sum(#{stockAmount}),0)",QueryCondition.eq("stock.oid",oid))
            .setExp("oweAmount",noAccount?"0":"#{stockAmount}-#{payAmount}")
            .setExp("payStatus",noAccount?"'W'":"'N'")
            .execute(oid);
    }

    /**
     * 提交
     */
    public void saveAndSubmit(StockInfo model, List<GoodsStockRecord> goodsList,boolean repositoryCheck) throws Exception {
        save(model,goodsList);
        model.setStatus(OrderModel.Status_Check);
        if(repositoryCheck) getService(OrderRepositoryCheckService.class).insertCheck(model);
        model.setSubmitDate(new Date());
        ModelUpdateUtil.updateModel(model,"status","submitDate");
    }
    public void saveAndSubmit(StockInfo model, List<GoodsStockRecord> goodsList) throws Exception {
        saveAndSubmit(model,goodsList,true);
    }

    /**
     * 删除
     */
    public void delete(String oid, UserInfo user) throws Exception {
        StockInfo model=ModelQueryList.getModel(StockInfo.class,oid,"*");
        ModelQueryCheck.init(model)
            .checkStrEq("status",OrderModel.Status_Register,"登记中才能删除")
            .checkStrEq("inputUser.oid",user.getOid(),"权限错误")
            .doCheck(false,true);
        ModelUpdateUtil.deleteModel(model);
        ModelUpdateUtil.delete(GoodsStockRecord.class, QueryCondition.eq("stock.oid",model.getOid()));
    }

    /**
     * 审核通过
     */
    public void check(String oid,Date stockDate,String remark, StoreInfo store,UserInfo user) throws Exception {
        getService(OrderRepositoryCheckService.class).verifyCheckOver(oid);
        StockInfo model=ModelQueryList.getModel(StockInfo.class,oid,"*");
        model.setStockDate(stockDate);
        model.setRemark(remark);
        ModelQueryCheck.init(model)
            .checkNotNull("stockDate","入库日期不能为空")
            .checkStrEq("status",OrderModel.Status_Check,"审核中才能通过")
            .checkStrEq("store.oid",store.getOid(),"权限错误")
            .doCheck(false,true);
        if(!StockInfo.Type_Begin.equals(model.getType()))
            PowerUtil.verifyAccountDate(model.getStockDate(),"入库日期");
        model.setStatus(OrderModel.Status_Done);
        model.setCheckUser(user);
        model.setCheckDate(new Date());
        ModelUpdateUtil.updateModel(model,"status","checkUser.oid","checkDate","stockDate","remark");
        //明细列表
        List<GoodsStockRecord> recordList=ModelQueryList.getModelList(GoodsStockRecord.class,
            new String[]{"*"}, null,
            QueryCondition.eq("stock.oid", model.getOid())
        );
        //更新商品信息
        if(ObjectUtil.notEmptyOid(model.getRefundSale())){
            recordList.forEach(item -> GoodsOutRecordSupport.add(item.getOutRecord().getOid(),model.getRefundSale().getOid(),item.getGoods().getOid()));
            GoodsOutRecordSupport.start();
        }else {
            recordList.forEach(item -> StoreGoodsSupport.add(item.getGoods().getOid()));
            StoreGoodsSupport.start();
        }
        //更新客户入库金额
        GuestStockSupport.add(model.getGuest().getOid());
        GuestStockSupport.start();
        //更新月度统计
        MonthRecordSupport.add(model.getInputUser().getOid(),model.getStockDate(),MonthRecord.Type_Stock);
        MonthRecordSupport.start();
    }

    /**
     * 退回
     */
    public void refund(String oid, StoreInfo store,UserInfo user) throws Exception {
        StockInfo model=ModelQueryList.getModel(StockInfo.class,oid,"*");
        ModelQueryCheck.init(model)
            .checkStrEq("status",OrderModel.Status_Check,"审核中才能退回")
            .checkStrEq("store.oid",store.getOid(),"权限错误")
            .doCheck(false,true);
        model.setStatus(OrderModel.Status_Register);
        model.setCheckUser(user);
        model.setCheckDate(new Date());
        model.setRepositoryStatus(StringUtil.isSpace(model.getRepositoryStatus())?null:OrderRepositoryCheck.Status_No);
        ModelUpdateUtil.updateModel(model,"status","checkUser.oid","checkDate","repositoryStatus");
    }
    public void updateInPayAmount(String stockOid) throws MException {
        ModelUpdate.init(StockInfo.class)
            .set("inPayAmount", PayAmountRecord.class,"ifnull(sum(#{payAmount}),0)",
                QueryCondition.and(
                    QueryCondition.eq("stock.oid",stockOid),
                    QueryCondition.not(QueryCondition.eq("pay.status", OrderModel.Status_Done))
                )
            )
            .execute(stockOid);
    }
}
